﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml.Serialization;
using Autodesk.Revit.DB;
using YArchitech.LIB;
using YArchitech.Revit;
using YJKRevitKernel.XYZUtility;
using YJKCopyModel.InteractiveOperation;
using YJKPresentation.Utils;

namespace YJKCopyModel.YJKRevitWndr
{
	public class DoorAndWindowManager
	{
		public static bool GetDoorAndWindowHeightByNo(ref double dHeight, string strNo)
		{
			try
			{
				Regex regex = new Regex("\\d+");
				MatchCollection matchCollection = regex.Matches(strNo);
				string text = string.Empty;
				foreach (object obj in matchCollection)
				{
					Match match = (Match)obj;
					bool flag = match.Value.Count<char>() == 4;
					if (flag)
					{
						text = match.Value;
						break;
					}
				}
				bool flag2 = !text.IsEmpty<char>();
				if (flag2)
				{
					string s = text.Substring(2);
					dHeight = double.Parse(s) * 100.0;
					return true;
				}
			}
			catch (Exception)
			{
			}
			return false;
		}

		public static Dictionary<DoorAndWindowBlockRefInfo, string> DistinguishNote(List<DoorAndWindowBlockRefInfo> lstBlockRefInfo, List<TextInfo> lstTextInfo)
		{
			Dictionary<DoorAndWindowBlockRefInfo, string> dictionary = new Dictionary<DoorAndWindowBlockRefInfo, string>();
			ToleranceManger toleranceManger = ToleranceManger.GetToleranceManger();
			double tolerance = toleranceManger.GetTolerance("门窗基线与其标注文本基线夹角");
			using (List<DoorAndWindowBlockRefInfo>.Enumerator enumerator = lstBlockRefInfo.GetEnumerator())
			{
				while (enumerator.MoveNext())
				{
					DoorAndWindowBlockRefInfo blockRef = enumerator.Current;
					string value = string.Empty;
					try
					{
						bool hasAttribute = blockRef.HasAttribute;
						if (hasAttribute)
						{
							TextInfo textInfo2 = lstTextInfo.Find((TextInfo textInfo) => textInfo.IsAttribute && textInfo.UseCadEntityOwnerHandle == blockRef.GuidInCad);
							bool flag = textInfo2 != null;
							if (flag)
							{
								value = textInfo2.UseText;
							}
						}
						else
						{
							XYZ handDir = blockRef.HandDir;
							value = DoorAndWindowManager.RecognitionNumber(lstTextInfo, handDir, blockRef.UseLocationPoint, tolerance);
						}
					}
					catch (Exception)
					{
					}
					dictionary.Add(blockRef, value);
				}
			}
			return dictionary;
		}

		public static EDoorAndWindowCategory GetDoorAndWindowCategory(string strBlockName, double dWidth)
		{
			EDoorAndWindowCategory result = EDoorAndWindowCategory.eDoor;
			try
			{
				bool flag = strBlockName.ToUpper().Contains("$WIN");
				if (flag)
				{
					result = EDoorAndWindowCategory.eWindow;
				}
				else
				{
					bool flag2 = strBlockName.ToUpper().Contains("$DORLIB");
					if (flag2)
					{
						result = EDoorAndWindowCategory.eDoor;
					}
					else
					{
						result = EDoorAndWindowCategory.eDoor;
					}
				}
			}
			catch (Exception)
			{
			}
			return result;
		}

		public static Dictionary<DoorAndWindowConfigInfo, List<DoorAndWindowBlockRefInfo>> GroupDoorAndWindow(List<DoorAndWindowBlockRefInfo> lstDoorAndWindowBlockRefInfo, List<TextInfo> lstText)
		{
			Dictionary<DoorAndWindowConfigInfo, List<DoorAndWindowBlockRefInfo>> dictionary = new Dictionary<DoorAndWindowConfigInfo, List<DoorAndWindowBlockRefInfo>>();
			try
			{
				Dictionary<DoorAndWindowBlockRefInfo, string> dictionary2 = DoorAndWindowManager.DistinguishNote(lstDoorAndWindowBlockRefInfo, lstText);
				bool flag = dictionary2 == null || lstDoorAndWindowBlockRefInfo.Count == 0;
				if (flag)
				{
					return null;
				}
				Dictionary<DoorAndWindowBlockRefInfo, DoorAndWindowConfigInfo> dictionary3 = new Dictionary<DoorAndWindowBlockRefInfo, DoorAndWindowConfigInfo>();
				foreach (KeyValuePair<DoorAndWindowBlockRefInfo, string> keyValuePair in dictionary2)
				{
					DoorAndWindowConfigInfo doorAndWindowConfigInfo = new DoorAndWindowConfigInfo();
					doorAndWindowConfigInfo.No = keyValuePair.Value;
					doorAndWindowConfigInfo.BlockNo = DoorAndWindowManager.GetDoorWindowBlockNo(keyValuePair.Key.BlockName);
					doorAndWindowConfigInfo.EnumCategory = DoorAndWindowManager.GetDoorAndWindowCategory(keyValuePair.Key.BlockName, keyValuePair.Key.Width);
					doorAndWindowConfigInfo.Width = DoorAndWindowManager.FormatWidth(keyValuePair.Key.Width);
					double height = 0.0;
					doorAndWindowConfigInfo.CanAnalyseNo = DoorAndWindowManager.GetDoorAndWindowHeightByNo(ref height, doorAndWindowConfigInfo.No);
					bool flag2 = !doorAndWindowConfigInfo.CanAnalyseNo;
					if (flag2)
					{
						bool flag3 = doorAndWindowConfigInfo.EnumCategory == EDoorAndWindowCategory.eDoor;
						if (flag3)
						{
							height = DoorAndWindowDefultSet.DoorHeight;
						}
						else
						{
							height = DoorAndWindowDefultSet.WindowHeight;
						}
					}
					doorAndWindowConfigInfo.Height = height;
					dictionary3.Add(keyValuePair.Key, doorAndWindowConfigInfo);
				}
				IEnumerable<IGrouping<string, KeyValuePair<DoorAndWindowBlockRefInfo, DoorAndWindowConfigInfo>>> enumerable = dictionary3.GroupBy(delegate(KeyValuePair<DoorAndWindowBlockRefInfo, DoorAndWindowConfigInfo> thisKeyValuePair)
				{
					StringBuilder stringBuilder = new StringBuilder();
					try
					{
						DoorAndWindowConfigInfo value3 = thisKeyValuePair.Value;
						stringBuilder.Append(value3.EnumCategory);
						stringBuilder.Append(value3.No);
						stringBuilder.Append(value3.CanAnalyseNo);
						stringBuilder.Append((int)value3.Width);
						stringBuilder.Append((int)value3.Height);
					}
					catch (Exception)
					{
					}
					return stringBuilder.ToString();
				});
				foreach (IGrouping<string, KeyValuePair<DoorAndWindowBlockRefInfo, DoorAndWindowConfigInfo>> source in enumerable)
				{
					Dictionary<DoorAndWindowBlockRefInfo, DoorAndWindowConfigInfo> dictionary4 = source.ToDictionary((KeyValuePair<DoorAndWindowBlockRefInfo, DoorAndWindowConfigInfo> k) => k.Key, (KeyValuePair<DoorAndWindowBlockRefInfo, DoorAndWindowConfigInfo> v) => v.Value);
					bool flag4 = dictionary4.IsEmpty<KeyValuePair<DoorAndWindowBlockRefInfo, DoorAndWindowConfigInfo>>();
					if (!flag4)
					{
						DoorAndWindowConfigInfo value = dictionary4.First<KeyValuePair<DoorAndWindowBlockRefInfo, DoorAndWindowConfigInfo>>().Value;
						List<DoorAndWindowBlockRefInfo> value2 = dictionary4.Keys.ToList<DoorAndWindowBlockRefInfo>();
						dictionary.Add(value, value2);
					}
				}
				IOrderedEnumerable<KeyValuePair<DoorAndWindowConfigInfo, List<DoorAndWindowBlockRefInfo>>> source2 = dictionary.OrderBy((KeyValuePair<DoorAndWindowConfigInfo, List<DoorAndWindowBlockRefInfo>> item) => item.Key, new ComparerDoorAndWindowConfigInfo());
				dictionary = source2.ToDictionary((KeyValuePair<DoorAndWindowConfigInfo, List<DoorAndWindowBlockRefInfo>> k) => k.Key, (KeyValuePair<DoorAndWindowConfigInfo, List<DoorAndWindowBlockRefInfo>> v) => v.Value);
			}
			catch (Exception ex)
			{
				return null;
			}
			return dictionary;
		}

		public static FamilySymbol CreateDoorWindowFamilySymbol(Autodesk.Revit.DB.Document doc, DoorAndWindowConfigInfo config)
		{
			FamilySymbol result = null;
			Transaction transaction = new Transaction(doc, "创建门窗族类型");
			try
			{
				transaction.Start();
				bool flag = config.TypeName == "<程序自选>";
				if (flag)
				{
					result = DoorAndWindowManager.DefaultFamilySymbol(doc, config.No, config.EnumCategory, config.BlockNo, config.Width, config.Height);
				}
				else
				{
					FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
					FilteredElementCollector filteredElementCollector2 = filteredElementCollector.OfClass(typeof(FamilySymbol));
					List<FamilySymbol> collection = filteredElementCollector2.OfCategory(BuiltInCategory.OST_Doors).Cast<FamilySymbol>().ToList<FamilySymbol>();
					filteredElementCollector = new FilteredElementCollector(doc);
					filteredElementCollector2 = filteredElementCollector.OfClass(typeof(FamilySymbol));
					List<FamilySymbol> collection2 = filteredElementCollector2.OfCategory(BuiltInCategory.OST_Windows).Cast<FamilySymbol>().ToList<FamilySymbol>();
					List<FamilySymbol> list = new List<FamilySymbol>();
					list.AddRange(collection);
					list.AddRange(collection2);
					string empty = string.Empty;
					FamilySymbol familySymbol = list.Find((FamilySymbol item) => item.Family.Name + ":" + item.Name == config.TypeName);
					string strNewNo = config.No;
					List<FamilySymbol> symbols = familySymbol.Family.GetSymbols();
                    Func<FamilySymbol, bool> ss9__1 = null;
					for (int i = 0; i < 2147483647; i++)
					{
						IEnumerable<FamilySymbol> source = symbols;
						Func<FamilySymbol, bool> matchFun;
						if ((matchFun = ss9__1) == null)
						{
							matchFun = (ss9__1 = ((FamilySymbol item) => item.Name == strNewNo));
						}
						bool flag2 = !source.Contains(matchFun);
						if (flag2)
						{
							break;
						}
						strNewNo = config.No + "(" + (i + 1).ToString() + ")";
					}
					result = DoorAndWindowManager.SelectFamilySymbol(strNewNo, familySymbol);
				}
				transaction.Commit();
			}
			catch (Exception)
			{
				bool flag3 = transaction.HasStarted();
				if (flag3)
				{
					transaction.RollBack();
				}
			}
			return result;
		}

		public static Dictionary<string, DoorAndWindowNumTransInfo> GetDoorAndWindowNumTransInfo()
		{
			Dictionary<string, DoorAndWindowNumTransInfo> result = new Dictionary<string, DoorAndWindowNumTransInfo>();
			try
			{
				string numbTransInfoFile = DoorAndWindowDefultSet.NumbTransInfoFile;
				List<DoorAndWindowNumTransInfo> source = new List<DoorAndWindowNumTransInfo>();
				XmlSerializer xmlSerializer = new XmlSerializer(typeof(List<DoorAndWindowNumTransInfo>));
				bool flag = File.Exists(numbTransInfoFile);
				if (flag)
				{
					using (FileStream fileStream = File.Open(numbTransInfoFile, FileMode.Open))
					{
						source = (xmlSerializer.Deserialize(fileStream) as List<DoorAndWindowNumTransInfo>);
						result = source.ToDictionary((DoorAndWindowNumTransInfo item) => item.Category.ToString() + item.No, (DoorAndWindowNumTransInfo item) => item);
					}
				}
			}
			catch (Exception ex)
			{
				throw;
			}
			return result;
		}

		public static string GetDoorWindowBlockNo(string strBlockName)
		{
			string result = string.Empty;
			try
			{
				int num = strBlockName.LastIndexOf("$");
				result = strBlockName.Substring(num + 1);
			}
			catch (Exception)
			{
			}
			return result;
		}

		private static FamilySymbol DefaultFamilySymbol(Autodesk.Revit.DB.Document doc, string strNo, EDoorAndWindowCategory eCategory, string strBlockNo, double dWidth, double dHeight)
		{
			Family family = DoorAndWindowManager.LoadFamily(doc, eCategory, strBlockNo, dWidth);
			bool flag = family == null;
			FamilySymbol result;
			if (flag)
			{
				result = null;
			}
			else
			{
				List<FamilySymbol> symbols = family.GetSymbols();
				bool flag2 = symbols.IsEmpty<FamilySymbol>();
				if (flag2)
				{
					result = null;
				}
				else
				{
					foreach (FamilySymbol familySymbol in symbols)
					{
						bool flag3 = !familySymbol.IsActive;
						if (flag3)
						{
							familySymbol.Activate();
						}
					}
					FamilySymbol familySymbol2 = symbols[0];
					bool flag4 = strNo.IsEmpty<char>();
					if (flag4)
					{
						strNo = DoorAndWindowManager.GetNoByDoorWindowFamilySymbol(familySymbol2, dWidth, dHeight);
					}
					FamilySymbol familySymbol3 = DoorAndWindowManager.CreateNewDoorWindowFamilySymbol(strNo, dWidth, dHeight, familySymbol2, symbols);
					result = familySymbol3;
				}
			}
			return result;
		}

		private static FamilySymbol SelectFamilySymbol(string strNo, FamilySymbol selectFamily)
		{
			bool flag = strNo.IsEmpty<char>();
			FamilySymbol familySymbol;
			if (flag)
			{
				familySymbol = selectFamily;
			}
			else
			{
				familySymbol = (selectFamily.Duplicate(strNo) as FamilySymbol);
			}
			bool flag2 = !familySymbol.IsActive;
			if (flag2)
			{
				familySymbol.Activate();
			}
			return familySymbol;
		}

		private static Family LoadFamily(Autodesk.Revit.DB.Document doc, EDoorAndWindowCategory eCategory, string strBlockNo, double dWidth)
		{
			Family result = null;
			try
			{
				Dictionary<string, DoorAndWindowNumTransInfo> doorAndWindowNumTransInfo = DoorAndWindowManager.GetDoorAndWindowNumTransInfo();
				bool flag = doorAndWindowNumTransInfo.IsEmpty<KeyValuePair<string, DoorAndWindowNumTransInfo>>();
				if (flag)
				{
					return null;
				}
				string key = eCategory.ToString() + strBlockNo;
				bool flag2 = !doorAndWindowNumTransInfo.ContainsKey(key);
				if (flag2)
				{
					bool flag3 = eCategory == EDoorAndWindowCategory.eDoor;
					if (flag3)
					{
						key = ((dWidth < DoorAndWindowDefultSet.SingleDoorWidthMax) ? (eCategory.ToString() + "00000001") : (eCategory.ToString() + "00000002"));
					}
					else
					{
						key = eCategory.ToString() + "00000001";
					}
				}
				string familyName = doorAndWindowNumTransInfo[key].FamilyName;
				List<Element> elementByClass = YJKElementFilter.GetElementByClass(typeof(Family), doc);
				foreach (Element element in elementByClass)
				{
					bool flag4 = ((Family)element).Name + ".rfa" == familyName;
					if (flag4)
					{
						result = (Family)element;
						return result;
					}
				}
				string text = string.Empty;
				bool flag5 = eCategory == EDoorAndWindowCategory.eDoor;
				if (flag5)
				{
					text = Path.Combine(Product.FamilyLocation, RevitVersion.GetVersionNumber(doc), DoorAndWindowDefultSet.DoorFamilyDir, familyName);
				}
				else
				{
					text = Path.Combine(Product.FamilyLocation, RevitVersion.GetVersionNumber(doc), DoorAndWindowDefultSet.WindowFamilyDir, familyName);
				}
                doc.LoadFamily(text, out result);
			}
			catch (Exception)
			{
				throw;
			}
			return result;
		}

		private static FamilySymbol CreateNewDoorWindowFamilySymbol(string strNo, double dWidth, double dHeight, FamilySymbol symbolDefault, List<FamilySymbol> lstSymbol)
		{
			FamilySymbol familySymbol = null;
			try
			{
				bool flag = lstSymbol.IsEmpty<FamilySymbol>();
				if (flag)
				{
					return null;
				}
				string strNewNo = strNo;
                Predicate<FamilySymbol> ss9__0 = null;
				for (int i = 0; i < lstSymbol.Count; i++)
				{
					Predicate<FamilySymbol> match;
					if ((match = ss9__0) == null)
					{
						match = (ss9__0 = ((FamilySymbol item) => item.Name == strNewNo));
					}
					bool flag2 = lstSymbol.Exists(match);
					bool flag3 = !flag2;
					if (flag3)
					{
						break;
					}
					strNewNo = strNo + "(" + (i + 1).ToString() + ")";
				}
				familySymbol = (symbolDefault.Duplicate(strNewNo) as FamilySymbol);
				Parameter parameter = familySymbol.GetParameter(BuiltInParameter.FAMILY_ROUGH_WIDTH_PARAM);
				bool flag4 = parameter != null;
				if (flag4)
				{
					parameter.Set(Common.MMToFeet(dWidth));
				}
				Parameter parameter2 = familySymbol.GetParameter(BuiltInParameter.FAMILY_ROUGH_HEIGHT_PARAM);
				bool flag5 = parameter2 != null;
				if (flag5)
				{
					parameter2.Set(Common.MMToFeet(dHeight));
				}
			}
			catch (Exception)
			{
			}
			return familySymbol;
		}

		private static string GetNoByDoorWindowFamilySymbol(FamilySymbol symboldouble, double dWidth, double dHeight)
		{
			string text = string.Empty;
			Regex regex = new Regex("^[A-Za-z]+");
			MatchCollection matchCollection = regex.Matches(symboldouble.Name);
			bool flag = matchCollection.Count == 0;
			string result;
			if (flag)
			{
				result = text;
			}
			else
			{
				text = matchCollection[0].Value;
				string str = ((int)DoorAndWindowManager.FormatWidth(dWidth) / 100).ToString("D2");
				string str2 = ((int)DoorAndWindowManager.FormatWidth(dHeight) / 100).ToString("D2");
				result = text + str + str2;
			}
			return result;
		}

		private static double FormatWidth(double dValue)
		{
			int num = 0;
			int a = (int)Math.Round(dValue);
			int num2 = Math.DivRem(a, 100, out num);
			bool flag = num < 50;
			double result;
			if (flag)
			{
				result = (double)(num2 * 100);
			}
			else
			{
				result = (double)(num2 * 100 + 100);
			}
			return result;
		}

		private static string RecognitionNumber(List<TextInfo> lstTextInfo, XYZ vcDoorHandleDir, XYZ ptDoorPos, double dTol)
		{
			string result = string.Empty;
			try
			{
				TextInfo textInfo = null;
				double num = double.MaxValue;
				foreach (TextInfo textInfo2 in lstTextInfo)
				{
					bool flag = textInfo2.ActualBox.IsEmpty<XYZ>() || textInfo2.ActualBox.Count != 4;
					if (!flag)
					{
						Line baseLine = textInfo2.GetBaseLine();
						bool flag2 = baseLine == null;
						if (!flag2)
						{
							XYZ direction = baseLine.Direction;
							double num2 = baseLine.Distance(ptDoorPos);
							bool flag3 = XYZUtilityMethod.IsParallel(direction, vcDoorHandleDir, dTol) && num2 < num;
							if (flag3)
							{
								textInfo = textInfo2;
								num = num2;
							}
						}
					}
				}
				bool flag4 = textInfo == null;
				if (flag4)
				{
					return result;
				}
				result = GeometryCommon.MergeNearTextNote(textInfo, lstTextInfo);
			}
			catch (Exception)
			{
			}
			return result;
		}
	}
}
